package com.vastcom.fabric.server.service.impl;

import com.vastcom.fabric.server.service.FabricService;
import com.vastcom.fabric.server.tools.*;
import org.hyperledger.fabric.sdk.*;
import org.hyperledger.fabric.sdk.exception.CryptoException;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.exception.TransactionException;
import org.hyperledger.fabric.sdk.security.CryptoSuite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Properties;

@Service
public class FabricServiceImpl implements FabricService {

    @Value("${fabric.orderer.name}")
    private String ordername;
    @Value("${fabric.orderer.grpcs.address}")
    private String ordergrpcaddress;

    private Logger log= LoggerFactory.getLogger(FabricServiceImpl.class);



//    @Autowired
//    private HFClient hfClient;

    @Override
    public UserContext getMyUserContext() {


        UserContext u= null;
        try {


            u = new UserContext();
            /*u.setAffiliation("rawmaterialMSP");
            u.setMspId("rawmaterialMSP");
            u.setAccount("张仓管");
            u.setName("cgadmin");*/
            u.setAffiliation("Org1MSP");
            u.setMspId("Org1MSP");
            u.setAccount("zzyadmin");
            u.setName("admin");
            //String parm1=FileTools.CRYPTO_PATH+FileTools.RAWMATERIA_ADMIN_CERT_FILENAME;
//            log.info("第一步+++++++++++++++++++++++++++++++");
            Enrollment enrollment= UserUtils.getEnrollment(
                    FileTools.CRYPTO_PATH+FileTools.RAWMATERIA_ADMIN_MSP_KEY_PATH
                    ,FileTools.RAWMATERIA_ADMIN_MSP_KWY_NAME,
                    FileTools.CRYPTO_PATH+FileTools.RAWMATERIA_ADMIN_CERT_PATH
                    ,FileTools.RAWMATERIA_ADMIN_CERT_FILENAME);

            u.setEnrollment(enrollment);
            log.info("getMyUserContext成功+++++++++++++++++++++++++++++++");

        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (CryptoException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

        return u;
    }

    @Override
    public HFClient getHfClient() {



            FabricClient fabricClient=new FabricClient(this.getMyUserContext());
            return fabricClient.hfClient;





    }


    @Override
    public HFClient getHfClientByOrg(String org) {
        return null;
    }

    @Override
    public Peer getPeer(String name, String grpcUrl, String tlsFilePath) {
        try {
            Properties properties=new Properties();
            properties.setProperty("pemFile",tlsFilePath);
            HFClient hfClient=this.getHfClient();
            Peer peer=hfClient.newPeer(name,grpcUrl,properties);
            return peer;
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
            return null;
        }

    }


    @Override
    public Peer getPeerByName(String name) {

        Peer result=null;
        String tlsfile=FileTools.CRYPTO_PATH;
        switch (name){
            case "Org1":
               /* tlsfile+="peerOrganizations/rawmaterial.4media.video/msp/tlscacerts/tlsca.rawmaterial.4media.video-cert.pem";
                result=this.getPeer("peer0.rawmaterial.4media.video",
                        "grpcs://peer0.rawmaterial.4media.video:7051",
                        tlsfile);*/
                 /* tlsfile+="peerOrganizations/rawmaterial.4media.video/msp/tlscacerts/tlsca.rawmaterial.4media.video-cert.pem";
                result=this.getPeer("peer0.rawmaterial.4media.video",
                        "grpcs://peer0.rawmaterial.4media.video:7051",
                        tlsfile);


                         */
                tlsfile+="peerOrganizations/org1.example.com/msp/tlscacerts/tlsca.org1.example.com-cert.pem";
                result=this.getPeer("peer0.org1.example.com",
                        "grpcs://peer0.org1.example.com:7051",
                        tlsfile);
                break;

            case "rawmateria_peer1":
                tlsfile+="peerOrganizations/rawmaterial.4media.video/msp/tlscacerts/tlsca.rawmaterial.4media.video-cert.pem";
                result=this.getPeer("peer1.rawmaterial.4media.video",
                        "grpcs://peer1.rawmaterial.4media.video:8051",
                        tlsfile);
                break;
            case "bake_p1":
                tlsfile="peerOrganizations/baker.4media.video/msp/tlscacerts/tlsca.baker.4media.video-cert.pem";
                result=this.getPeer("peer0.baker.4media.video",
                        "grpcs://peer0.baker.4media.video:9051",
                        tlsfile);


                break;

            case "back_p2":
                tlsfile="peerOrganizations/baker.4media.video/msp/tlscacerts/tlsca.baker.4media.video-cert.pem";
                result=this.getPeer("peer1.baker.4media.video",
                        "grpcs://peer1.baker.4media.video:10051",
                        tlsfile);
                break;





        }



        return result;
    }

    @Override
    public Channel createChannel() {
        String txPath="/opt/goworkspace/src/github.com/hyperledger/fabric-samples/my-network/channel-artifacts/sigma.tx";
//String txPath="/Users/albatross/tempfolder/sigma.tx";

        try {

            FabricClient client=new FabricClient(this.getMyUserContext());

            String tlscapath= FileTools.CRYPTO_PATH+FileTools.ORDERER_TLS_FILE;
            Properties properties = new Properties();
            properties.setProperty("pemFile",tlscapath);
            Orderer orderer = client.hfClient.newOrderer("orderer.4media.video",
                    "grpcs://orderer.4media.video:7050",
                    properties
            );
            String tlsfileforpeer=FileTools.CRYPTO_PATH;
            tlsfileforpeer+="peerOrganizations/rawmaterial.4media.video/msp/tlscacerts/tlsca.rawmaterial.4media.video-cert.pem";
            ///peerOrganizations/rawmaterial.4media.video/msp/tlscacerts/tlsca.rawmaterial.4media.video-cert.pem
            Properties propertiesforpeer=new Properties();
            propertiesforpeer.setProperty("pemFile",tlsfileforpeer);
            Peer peer=client.hfClient.newPeer("peer0.rawmaterial.4media.video",
                    "grpcs://peer0.rawmaterial.4media.video:7051"
                    ,propertiesforpeer);
            //Peer peer1=client.getPeerByName(Const.PEER_ONE_RAW_MATERIA_NAME);

          Channel channel=  client.createChannel("sigma",orderer,txPath);
          if(channel!=null){
              channel.addOrderer(orderer);
              channel.addPeer(peer);

              channel.initialize();
              return channel;
          }


        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        } catch (TransactionException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public Channel getCannelByName(String name) {
     FabricClient client=new FabricClient(this.getMyUserContext());
      return client.hfClient.getChannel(name);
      //return client.getChannleByName(name);






    }


    @Override
    public boolean initChannel() {
        try {

            //Channel channel=this.getCannelByName("sigmaforadmin");

            HFClient hfClient=this.getHfClient();
            Channel channel=hfClient.newChannel("sigmaformember");
            if(channel!=null){
                Orderer orderer=this.getOrderer();
                channel.addOrderer(orderer);
                Peer rawp0=this.getPeerByName(Const.PEER_RAW_MATERIA_NAME);
                channel.addPeer(rawp0);
                Peer rawp1=this.getPeerByName(Const.PEER_ONE_RAW_MATERIA_NAME);
                channel.addPeer(rawp1);
//                Peer bakep0=this.getPeerByName(Const.PEER_BAKE_NAME);
//                channel.addPeer(bakep0);
//                Peer back1=this.getPeerByName(Const.PEER_ONE_BAKE);
//                channel.addPeer(back1);
                channel.initialize();
            return true;
            }
            else {
                log.error("get Channel by name is empty");
                return false;
            }
        } catch (InvalidArgumentException | TransactionException e) {
            e.printStackTrace();
        }


        return false;
    }

    @Override
    public Orderer getOrderer(String name, String grpcurl, String tlsfilePath) {
        try {
            Properties properties=new Properties();
            properties.setProperty("pemFile",tlsfilePath);
            HFClient hfclient=this.getHfClient();
            Orderer orderer=hfclient.newOrderer(name,grpcurl,properties);

            return orderer;
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        }
        return null;
    }


    @Override
    public Orderer getOrderer() {
        String tlscapath=FileTools.CRYPTO_PATH+FileTools.ORDERER_TLS_FILE;
        Orderer temp=this.getOrderer(this.ordername,
                this.ordergrpcaddress,
                tlscapath
                );

        return temp;
    }




}
